﻿@page "/ru/5.8/software-configuration/using-formulas"
@{
    Layout = "_ArticleLayout";
    ViewBag.Title = "Использование формул";
}

<nav class="doc-toc">
    <div class="h6">На этой странице</div>
    <hr>
    <ul>
        <li><a href="#formula-rules">Правила написания формул</a></li>
        <li><a href="#existing-formulas">Существующие формулы</a></li>
        <li><a href="#debugging-formulas">Отладка формул</a></li>
    </ul>
</nav>

<div class="doc-content">
    <h1>Использование формул</h1>

    <p>Формулы применяются для расчёта значений и статусов входных каналов, а также для расчёта значений команд управления. Обработка формул выполняется программой Сервер.</p>

    <p>Выполняемые формулы вводятся в базу конфигурации в таблицы <em>Входные каналы</em> и <em>Каналы управления</em> в столбец <em>Формула</em>. Чтобы расчёт по формуле для какого-либо канала выполнялся, необходимо установить для него галочку в столбце <em>Исп. формулу</em>. Таблица <em>Формулы</em> базы конфигурации содержит дополнительные функции и структуры данных, которые могут быть использованы в формулах для входных каналов и каналов управления.</p>

    <h2 id="formula-rules">Правила написания формул</h2>

    <p>Общие правила написания и использования формул:</p>

    <ol>
        <li>Формулы записываются согласно <a href="https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/" target="_blank">синтаксису математических выражений языка C#</a>. Доступны различные классы .NET, например, Math, DateTime.</li>
        <li>База конфигурации позволяет добавлять новые константы, поля, свойства и методы, которые становятся доступны в формулах.</li>
        <li>Если хотя бы одна из формул содержит ошибку, работа Сервера невозможна. Информация об ошибках в формулах выводится в журнал приложения.</li>
    </ol>

    <p>Правила вычисления формул входных каналов:</p>

    <ol>
        <li>Расчёт по формулам для каналов типа <em>Телесигнал</em> и <em>Телеизмерение</em> выполняется только при получении сервером новых данных по этим каналам. Используйте эти типы каналов, если формула не ссылается на данные других каналов.</li>
        <li>Расчёт по формулам для каналов типа <em>Дорасчётный *</em> и <em>Кол-во переключений</em> выполняется постоянно. Последовательность расчёта – от меньших номеров каналов к большим. Дорасчётные типы каналов используются, если значение и статус канала вычисляются на основе данных других каналов.</li>
        <li>Расчёт по формулам для каналов типа <em>Минутный *</em> и <em>Часовой *</em> выполняется периодически один раз в минуту или один раз в час соответственно. Используйте эти типы каналов для реализации различных счётчиков, например, потребляемой энергии или времени наработки.</li>
        <li>Статус канала после вычисления по формуле для каналов типа <em>Телесигнал</em> и <em>Телеизмерение</em> равен статусу переданных Серверу данных, если расчёт статуса не задан в формуле явно.</li>
        <li>Для каналов других типов устанавливается статус <em>Параметр определён</em>, если расчёт статуса не задан в формуле явно.</li>
        <li>Формула, заданная для входного канала в базе конфигурации и не содержащая символа &quot;;&quot;, определяет расчёт значения канала.</li>
        <li>Если формула содержит символ «;», то она разбивается на две части: первая часть определяет расчёт значения канала, вторая часть – расчёт статуса канала.</li>
        <li>Если для канала заданы границы, то статус канала пересчитывается с учётом границ после вычисления формулы канала.</li>
        <li>Формула для расчёта значения канала должна возвращать вещественное число типа <em>double</em>, а формула для расчёта статуса - целое число типа <em>int</em>.</li>
    </ol>

    <p>Правила вычисления формул каналов управления:</p>

    <ol>
        <li>Формула, заданная для канала управления в базе конфигурации, применяется для каналов управления с типом команды <em>Стандартная</em> или <em>Бинарная</em>.</li>
        <li>Формула для расчёта значения стандартной команды должна возвращать вещественное число типа <em>double</em>, а формула для расчёта данных бинарной команды - массив байт типа <em>byte[]</em>.</li>
    </ol>


    <h2 id="existing-formulas">Существующие формулы</h2>

    <p>Переменные, доступные в формулах:</p>

    <table class="table table-hover">
        <thead>
            <tr>
                <th>Переменная</th>
                <th>Тип значения</th>
                <th>Описание</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>CnlVal, Cnl</td>
                <td>double</td>
                <td>Передаваемое Серверу значение входного канала до расчёта</td>
            </tr>
            <tr>
                <td>CnlStat</td>
                <td>int</td>
                <td>Передаваемый Серверу статус входного канала до расчёта</td>
            </tr>
            <tr>
                <td>CmdVal, Cmd</td>
                <td>double</td>
                <td>Передаваемое Серверу значение команды управления</td>
            </tr>
            <tr>
                <td>CmdData</td>
                <td>byte[]</td>
                <td>Передаваемые Серверу данные команды управления</td>
            </tr>
            <tr>
                <td>CnlNum</td>
                <td>int</td>
                <td>Номер канала, формула которого вычисляется</td>
            </tr>
            <tr>
                <td>E</td>
                <td>double</td>
                <td>Число e</td>
            </tr>
            <tr>
                <td>PI</td>
                <td>double</td>
                <td>Число π</td>
            </tr>
        </tbody>
    </table>

    <p>Функции, доступные в формулах:</p>

    <table class="table table-hover">
        <thead>
            <tr>
                <th>Функция</th>
                <th>Тип значения</th>
                <th>Описание</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>N(n)</td>
                <td>int</td>
                <td>Возвращает номер заданного канала для обновления номеров при клонировании</td>
            </tr>
            <tr>
                <td>Val()</td>
                <td>double</td>
                <td>Текущее значение входного канала вычисляемой формулы</td>
            </tr>
            <tr>
                <td>Val(n)</td>
                <td>double</td>
                <td>Текущее значение входного канала n</td>
            </tr>
            <tr>
                <td>SetVal(n, val)</td>
                <td>double</td>
                <td>Установить текущее значение входного канала n</td>
            </tr>
            <tr>
                <td>Stat()</td>
                <td>int</td>
                <td>Текущий статус входного канала вычисляемой формулы</td>
            </tr>
            <tr>
                <td>Stat(n)</td>
                <td>int</td>
                <td>Текущий статус входного канала n</td>
            </tr>
            <tr>
                <td>SetStat(n, stat)</td>
                <td>int</td>
                <td>Установить текущий статус входного канала n</td>
            </tr>
            <tr>
                <td>SetData(n, val, stat)</td>
                <td>double</td>
                <td>Установить текущее значение и статус входного канала n</td>
            </tr>
            <tr>
                <td>Abs(x)</td>
                <td>double</td>
                <td>Модуль</td>
            </tr>
            <tr>
                <td>Sin(x)</td>
                <td>double</td>
                <td>Синус</td>
            </tr>
            <tr>
                <td>Cos(x)</td>
                <td>double</td>
                <td>Косинус</td>
            </tr>
            <tr>
                <td>Tan(x)</td>
                <td>double</td>
                <td>Тангенс</td>
            </tr>
            <tr>
                <td>Exp(x)</td>
                <td>double</td>
                <td>Экспонента</td>
            </tr>
            <tr>
                <td>Ln(x), Log(x)</td>
                <td>double</td>
                <td>Натуральный логарифм</td>
            </tr>
            <tr>
                <td>Sqr(x)</td>
                <td>double</td>
                <td>Квадрат числа</td>
            </tr>
            <tr>
                <td>Sqrt(x)</td>
                <td>double</td>
                <td>Квадратный корень</td>
            </tr>
        </tbody>
    </table>

    <p>Дополнительные формулы, в том числе формулы для работы со средними значениеми, <a href="https://github.com/RapidScada/scada-community/tree/master/Formulas" target="_blank">доступны на GitHub</a>.</p>

    <h2 id="debugging-formulas">Отладка формул</h2>

    <p>При разработке собственных формул необходимо обеспечивать корректность синтаксиса формул и правильность их работы. Если службе Сервера при запуске не удалось скомпилировать формулы, информация об ошибке выводится в журнал работы Сервера, а компилируемый код формул доступен в файле CalcEngine.cs, который расположен по умолчанию в директории журналов Сервера C:\SCADA\ScadaServer\Log\</p>

    <p>Для разработки сложных формул рекомендуется использовать Microsoft Visual Studio Community Edition, подключив в зависимости проекта сборку FormulaTester.dll. В качестве примера можно использовать проект формул указанный выше.</p>
</div>
